`include "../codigo/Ram.v"

module test_ram();

    // Signs.
    reg [0:0] clock1;
    reg [0:0] reset1;
    reg [31:0] addr1;
    reg [0:0] rw1;
    reg [0:0] en1h1;
    reg [0:0] en1l1;
    reg [0:0] en2h1;
    reg [0:0] en2l1;

    // Wires (inout).
    wire [7:0] data1h1;
    wire [7:0] data1l1;
    wire [7:0] data2h1;
    wire [7:0] data2l1;

    // Auxiliar registers.
    reg [7:0] writeReg1;
    reg [7:0] writeReg2;
    reg [7:0] writeReg3;
    reg [7:0] writeReg4;


    // Assigns wires to inout. The meaning is: If we are reading information
    // from memory, one wire's ending is receiving the data and the other ending 
    // is receiving no data. So, we don't have conflicts.
    assign data1h1 =  (en1h1 && !rw1) ? 8'bz : writeReg1;
    assign data1l1 =  (en1l1 && !rw1) ? 8'bz : writeReg2;
    assign data2h1 =  (en2h1 && !rw1) ? 8'bz : writeReg3;
    assign data2l1 =  (en2l1 && !rw1) ? 8'bz : writeReg4;

    //Defines clock.
    initial begin
         clock1 = 1'b0;
    end
    always begin 
        #3 clock1 = ~clock1;
    end

    task Writing;
        //Write data in the 10th memory position, if succed is expected that 
	//the reading operation is succesfull, reading the data in the write
	//registers

	begin
            // Write mode Enabled.
             rw1 = #0 1'b1;
            // Memory Address.
             addr1 = #0 32'd10;
        
            // Buses Enabled.
             en1h1 = #0 1'b1;
             en1l1 = #0 1'b1;
             en2h1 = #0 1'b1;
             en2l1 = #0 1'b1;

            // Data to Write.
            // Bus 1
             writeReg1 = #0 11;
            // Bus 2
             writeReg2 = #0 8'd22;
            // Bus 3
             writeReg3 = #0 -8'd33;
            // Bus 4
             writeReg4 = #0 8'd44;
        end
    endtask 

    task Reading;
        //Reading data from the memory, is expected that the data contained in
	//the memory is equal to the data contained in the write registers,
	//since these data were not changed.

	begin
            // Read mode Enabled.
             rw1 = #0 1'b0;

            // Buses Enabled.
             en1h1 = #0 1'b1;
             en1l1 = #0 1'b1;
             en2h1 = #0 1'b1;
             en2l1 = #0 1'b1;
        end
    endtask

    task Reset;
        //Just reset the content in the memory, so we expect that any memory
	//position will be set to 0.
	begin            
	//Reset.
             reset1 = #0 1'b0;
             reset1 = #0 1'b1;
        end
    endtask

    task Disable_Bus;
        //Disable bus to test if any data is placed in the memory without 
	//their sign set to 1; This test expects that there will be no 
	//writing/reading operation
	begin
            // Buses Disabled.
             en1h1 = #0 1'b0;
             en1l1 = #0 1'b0;
             en2h1 = #0 1'b0;
             en2l1 = #0 1'b0;
        end
    endtask

    task Change_Input_Values;
        //Change the data in the write register to help the tests
	begin
            // Write mode Enabled.                                                                                                     
            rw1 = #0 1'b1;
            // Bus 1
             writeReg1 = #0 8'd10;
            // Bus 2
             writeReg2 = #0 8'd20;
            // Bus 3
             writeReg3 = #0 8'd30;
            // Bus 4
             writeReg4 = #0 8'd40;
        end
    endtask

   initial begin   

       $dumpfile("../test_ram.vcd");
       $dumpvars(0);
       // Monitoring variables,
       $monitor("Cycle: %d;\nClock: %d\nRw: %d\nAddr: %d\nReset: %d\nEn1h1: %d | Data1h1: %d | WriteReg1: %d;\nEn1l1: %d | Data1l1: %d | WriteReg2: %d;\nEn2h1: %d | Data2h1: %d | WriteReg3: %d;\nEn2l1: %g | Data2l1: %d | WriteReg4: %d;\n\n---------------------------------------------------\n",$time,clock1,rw1,addr1,reset1,en1h1,data1h1,writeReg1,en1l1,data1l1,writeReg2,en2h1,data2h1,writeReg3,en2l1,data2l1,writeReg4);

       reset1 = #0 1;
       #1
       Writing;
       #6
       Reading;
       #6
       Reset;
       #1
       Disable_Bus;    
       #4
       Change_Input_Values;
       #1
       Reading;

       #5 $finish;

    end
    Ram ram(clock1,reset1,addr1,rw1,en1h1,data1h1,en1l1,data1l1,en2h1,data2h1,en2l1,data2l1);
endmodule
